"""
File management utilities for Excel file handling.

This module provides the FileManager class for handling Excel file selection,
validation, and basic file operations required by the preprocessing pipeline.
"""

import os
import tkinter as tk
from tkinter import filedialog, messagebox
from typing import Optional
import logging

from .exceptions import FileOperationError
from .validation import InputValidator
from .error_recovery import handle_file_operations, ErrorRecoveryManager


class FileManager:
    """
    Handles Excel file selection and validation operations.
    
    This class provides methods for selecting Excel files through a GUI dialog,
    validating file formats, and checking file accessibility.
    """
    
    SUPPORTED_EXTENSIONS = {'.xlsx', '.xls'}
    
    def __init__(self, error_recovery_manager: Optional[ErrorRecoveryManager] = None):
        """
        Initialize the FileManager.
        
        Args:
            error_recovery_manager: Optional error recovery manager for handling errors
        """
        # Initialize tkinter root window (hidden)
        self._root = None
        self.logger = logging.getLogger(__name__)
        self.error_recovery_manager = error_recovery_manager or ErrorRecoveryManager(self.logger)
    
    def _ensure_root(self):
        """Ensure tkinter root window exists."""
        try:
            if self._root is None:
                self._root = tk.Tk()
                self._root.withdraw()  # Hide the root window
        except Exception as e:
            raise FileOperationError(
                "Failed to initialize GUI components",
                operation="gui_init",
                details=f"Tkinter initialization failed: {str(e)}"
            )
    
    @handle_file_operations()
    def select_file(self) -> Optional[str]:
        """
        Open file dialog and return selected Excel file path.
        
        Returns:
            Optional[str]: Path to selected Excel file, or None if cancelled
            
        Raises:
            FileOperationError: If file dialog fails or file validation fails
        """
        try:
            # 首先尝试GUI文件对话框
            try:
                self._ensure_root()
                
                print("正在打开文件选择对话框...")
                print("如果对话框没有出现，请检查任务栏或按Alt+Tab切换窗口")
                
                file_path = filedialog.askopenfilename(
                    title="Select Excel File",
                    filetypes=[
                        ("Excel files", "*.xlsx *.xls"),
                        ("Excel 2007+ files", "*.xlsx"),
                        ("Excel 97-2003 files", "*.xls"),
                        ("All files", "*.*")
                    ]
                )
                
                if file_path:
                    # Use comprehensive validation
                    self.validate_excel_file(file_path)
                    self.logger.info(f"Selected Excel file: {file_path}")
                    return file_path
                else:
                    # 如果用户取消了对话框，提供命令行输入选项
                    return self._manual_file_input()
                    
            except Exception as gui_error:
                print(f"文件对话框打开失败: {gui_error}")
                print("切换到手动输入模式...")
                return self._manual_file_input()
                
        except Exception as e:
            if isinstance(e, FileOperationError):
                raise
            raise FileOperationError(
                "File selection failed",
                operation="file_dialog",
                details=str(e)
            )
    
    def _manual_file_input(self) -> Optional[str]:
        """
        手动输入文件路径的备用方法
        
        Returns:
            Optional[str]: 用户输入的文件路径，或None如果取消
        """
        print("\n" + "="*50)
        print("手动文件选择")
        print("="*50)
        print("请输入Excel文件的完整路径，或者:")
        print("- 输入 'q' 或 'quit' 退出")
        print("- 直接按Enter取消选择")
        print("- 可以拖拽文件到命令行窗口")
        print("\n提示: 文件路径示例:")
        print("  C:\\Users\\用户名\\Documents\\data.xlsx")
        print("  ./data/sample_data.xlsx")
        print("  data\\my_file.xlsx")
        
        while True:
            try:
                file_path = input("\n请输入文件路径: ").strip()
                
                # 检查退出命令
                if file_path.lower() in ['q', 'quit', 'exit']:
                    print("已取消文件选择")
                    return None
                
                # 检查空输入
                if not file_path:
                    print("已取消文件选择")
                    return None
                
                # 清理路径（移除引号）
                file_path = file_path.strip('"\'')
                
                # 验证文件
                self.validate_excel_file(file_path)
                print(f"✓ 文件验证成功: {file_path}")
                self.logger.info(f"Manually selected Excel file: {file_path}")
                return file_path
                
            except FileOperationError as e:
                print(f"✗ 文件验证失败: {e.get_user_message()}")
                print("请重新输入正确的文件路径")
                continue
            except KeyboardInterrupt:
                print("\n已取消文件选择")
                return None
            except Exception as e:
                print(f"✗ 输入错误: {e}")
                print("请重新输入")
                continue
    
    def validate_excel_file(self, file_path: str) -> None:
        """
        Validate Excel file format and accessibility.
        
        Args:
            file_path (str): Path to the Excel file to validate
            
        Raises:
            FileOperationError: If validation fails
        """
        try:
            # 基本文件检查
            if not file_path or not isinstance(file_path, str):
                raise FileOperationError(
                    "Invalid file path",
                    file_path=str(file_path),
                    operation="validate",
                    details="File path must be a non-empty string"
                )
            
            # 检查文件是否存在
            if not os.path.exists(file_path):
                raise FileOperationError(
                    "File does not exist",
                    file_path=file_path,
                    operation="validate"
                )
            
            # 检查是否是文件（不是目录）
            if not os.path.isfile(file_path):
                raise FileOperationError(
                    "Path is not a file",
                    file_path=file_path,
                    operation="validate",
                    details="Path points to a directory or special file"
                )
            
            # 检查文件扩展名
            file_ext = os.path.splitext(file_path)[1].lower()
            if file_ext not in self.SUPPORTED_EXTENSIONS:
                raise FileOperationError(
                    f"Unsupported file format '{file_ext}'",
                    file_path=file_path,
                    operation="validate",
                    details=f"Supported formats: {', '.join(self.SUPPORTED_EXTENSIONS)}"
                )
            
            # 检查文件大小（不能为空）
            try:
                file_size = os.path.getsize(file_path)
                if file_size == 0:
                    raise FileOperationError(
                        "File is empty",
                        file_path=file_path,
                        operation="validate"
                    )
            except OSError as e:
                raise FileOperationError(
                    "Cannot access file size",
                    file_path=file_path,
                    operation="validate",
                    details=str(e)
                )
            
            # 检查文件读取权限
            if not os.access(file_path, os.R_OK):
                raise FileOperationError(
                    "File is not readable",
                    file_path=file_path,
                    operation="validate",
                    details="Check file permissions"
                )
            
            self.logger.info(f"Excel file validation passed: {file_path}")
            
        except FileOperationError as e:
            # Re-raise FileOperationError as-is
            raise
        except Exception as e:
            error = FileOperationError(
                "Unexpected error during file validation",
                file_path=file_path,
                operation="validate",
                details=str(e)
            )
            raise error
    
    def _show_error(self, title: str, message: str):
        """
        Display error message to user.
        
        Args:
            title (str): Error dialog title
            message (str): Error message to display
        """
        try:
            # 尝试显示GUI错误对话框
            self._ensure_root()
            messagebox.showerror(title, message)
        except Exception:
            # 如果GUI失败，在控制台显示错误
            print(f"\n✗ {title}: {message}")
            self.logger.error(f"{title}: {message}")
    
    def cleanup(self):
        """Clean up tkinter resources."""
        if self._root:
            self._root.destroy()
            self._root = None